#ifndef LOGGER_H
#define LOGGER_H
#include <iostream>
#include <sstream>
#include <log4cpp/OstreamAppender.hh>
#include <log4cpp/PatternLayout.hh>
#include <log4cpp/Category.hh>
#include <log4cpp/FileAppender.hh>
#include <log4cpp/RollingFileAppender.hh>
using namespace std;
using namespace log4cpp;

#define LOG_WARN(msg) logger::getInstance()->warn(__FILE__,__LINE__,__FUNCTION__,msg);
#define LOG_ERROR(msg) logger::getInstance()->error(__FILE__,__LINE__,__FUNCTION__,msg);
#define LOG_DEBUG(msg) logger::getInstance()->debug(__FILE__,__LINE__,__FUNCTION__,msg);
#define LOG_INFO(msg) logger::getInstance()->info(__FILE__,__LINE__,__FUNCTION__,msg);

class logger
{
public:
    void warn(const char* file,int line,const char * func,const char *msg);
    void error(const char *file,int line , const char *func,const char *msg);
    void debug(const char *file,int line , const char *func,const char *msg);
    void info(const char *file,int line , const char *func,const char *msg);



    static logger* getInstance(){
        if(_pInstance == nullptr){
            _pInstance = new logger();

            PatternLayout * ptn1 = new PatternLayout();
            ptn1->setConversionPattern("%d %c [%p] %m%n");

            PatternLayout *ptn2 = new PatternLayout();
            ptn2->setConversionPattern("%d %c [%p] %m%n");

            OstreamAppender * ost = new OstreamAppender("console",&cout);
            ost->setLayout(ptn1);

            RollingFileAppender *rfPos =new RollingFileAppender("server","./log/server.log",5*1024,9);
            rfPos->setLayout(ptn2);

            _root = &(Category::getRoot());
            _root->setPriority(Priority::DEBUG);
            _root->addAppender(ost);
            _root->addAppender(rfPos);
        }

        return _pInstance;
    }


    static void destroy(){
        if(_pInstance != nullptr){
            Category::shutdown();
            _root = nullptr;
            delete _pInstance;
            _pInstance = nullptr;
        }
    }

private:
    logger();
    ~logger();
    logger(const logger&) = delete;
    logger & operator=(const logger &) = delete;
    static logger*_pInstance;
    static Category *_root;
};

#endif

